import React, {FC, useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {Avatar, Breadcrumb, Col, Dropdown, Layout, Row, Tabs} from "antd";
import "./css/Main.less";
import useStateRef from '../customUse/useStateRef.tsx';
import GlobalIcon from "../global/GlobalIcon.tsx";
import {getLocale} from '../../i18n/i18n.tsx';
import {useTranslation} from "react-i18next";
import logoImg from "@src/images/logo.png"
import {useNavigate, useParams} from "react-router";
import {getUserInfo} from "../services/SecurityService.tsx";
import {coreConnect} from "../utils/StoreUtil.tsx";
import {Panel, PanelGroup, PanelResizeHandle} from "react-resizable-panels";
import {setViewMap} from "../services/ViewService.tsx";
import TabContent from './content/TabContent.tsx';
import DetailsContent from './content/DetailsContent.tsx';
import IframeContent from './content/IframeContent.tsx';
import LeftMenu from './menu/LeftMenu.tsx';
import RightMenu from './menu/RightMenu.tsx';
import Config from "../Config.tsx";
import {isArray, strToObject} from "../utils";
import {loadMenu, loadVirtualMenu} from "../services/MenuService.tsx";

const menuReg: any = /([^\/]+)\-([^\/]+)\-([^\/]+)/g;

interface MainProps {
    tabMap: any,
    userId: string,
    themeToken: any,
    dispatch: Function
}

const Main: FC<MainProps> = (props) => {
    const {t} = useTranslation();
    const menuIdRef = useRef(null);
    const isTabChangingRef = useRef(false);

    const {menuId} = useParams();
    const navigateTo = useNavigate();
    const userInfo = getUserInfo();

    const defaultTab: object = {
        label: (<div>
            <GlobalIcon name={"icon-home"}
                        className={"sf_core_main_layout_content_tabs_main_home"}/>
            <span>{t("home")}</span>
        </div>),
        key: "home",
        labelCn: "首页",
        labelEn: "Home",
        labelPt: "Home",
        tabType: "tab",
        tabParams: {
            url: "",
            menuId: Config.homeMenuId
        },
        children: null,
        closable: false
    };

    const tabMenu: object[] = [
        {
            key: "refreshPage",
            label: t("refreshPage"),
            size: "small",
            icon: <GlobalIcon name={"icon-refresh"}/>
        }, {
            key: "closeCur",
            label: t("closeCur"),
            size: "small",
            icon: <GlobalIcon name={"icon-close"}/>
        }, {
            key: "closeOther",
            label: t("closeOther"),
            size: "small",
            icon: <GlobalIcon name={"icon-close-other"}/>
        }, {
            key: "closeLeft",
            label: t("closeLeft"),
            size: "small",
            icon: <GlobalIcon name={"icon-close-left"}/>
        }, {
            key: "closeRight",
            label: t("closeRight"),
            size: "small",
            icon: <GlobalIcon name={"icon-close-right"}/>
        }, {
            key: "closeAll",
            label: t("closeAll"),
            size: "small",
            icon: <GlobalIcon name={"icon-close-all"}/>
        }
    ];
    const tabsRef = useRef([]),
        leftMenuRef = useRef();

    const [tabs, setTabs] = useStateRef([], tabsRef),
        [activeTab, setActiveTab] = useState<any>(),
        [isFold, setIsFold] = useState<boolean>(false);

    const getLeftWidth = useCallback((num) => {
        return num / window.innerWidth * 100;
    }, [])

    const loadDefaultMenu: Function = useCallback(async (menuId: string) => {
        const arr: string[] = menuReg.exec(menuId);
        let menu = {}, otherParams = {};
        if (arr) {
            menu = await loadVirtualMenu({objectTypeName: arr[2], objectStatusId: arr[3], menuType: "MENU"});
            isArray(menu) && (menu = menu[0]);
            otherParams = {
                objectId: arr[1],
                objectTypeId: arr[2],
                objectStatusId: arr[3],
                tabType: "details"
            }
        } else {
            menu = await loadMenu({id: menuId});
            otherParams = {
                url: menu.url,
                menuId: menu.id,
                tabType: menu.isOutside ? "iframe" : "tab",
            }
        }
        const operate = strToObject(menu.operate);
        const tab: any = {
            key: menu.id,
            label: getLocale(menu.zhCn, menu.usEn, menu.ptBr),
            labelCn: menu.zhCn,
            labelEn: menu.usEn,
            labelPt: menu.ptBr,
            tabType: otherParams.tabType,
            tabParams: {
                ...otherParams,
                ...operate
            }
        }
        props.dispatch({
            type: "tabsReducer/addTabs",
            payload: {data: tab}
        });
        return tab;
    }, []);

    const initTabs = useCallback(async () => {
        const tabs = props.tabMap[props.userId] || [];
        let newActiveTab = tabs.find((item: any) => (item.key === menuId));
        if (!newActiveTab && menuId) {
            newActiveTab = await loadDefaultMenu(menuId);
            setTabs([defaultTab, ...tabs, newActiveTab]);
        } else {
            newActiveTab = newActiveTab || defaultTab;
            setTabs([defaultTab, ...tabs]);
        }
        setActiveTab(newActiveTab);
    }, [props.tabMap, props.userId, menuId]);

    useEffect(() => {
        if (isTabChangingRef.current) {
            isTabChangingRef.current = false
            return;
        }
        initTabs();
    }, [props.tabMap, props.userId, menuId]);

    const getComByType = useCallback((type: any) => {
        let com;
        switch (type) {
            case "tab":
                com = TabContent;
                break;
            case "iframe":
                com = IframeContent;
                break;
            case "details":
                com = DetailsContent;
                break;
            default:
                com = TabContent;
        }
        return com;
    }, []);

    const tabChange = useCallback((activeKey: string) => {
        setTimeout(() => {
            if (activeKey === "home") {
                navigateTo("/home")
            } else {
                navigateTo(`/home/${activeKey}`);
            }
        }, 0)
    }, [tabs]);

    const tabEdit = useCallback((targetKey: string, action: string) => {
        if (action === "remove") {
            isTabChangingRef.current = true;
            const index = tabs.findIndex((i: any) => (i.key === targetKey));
            const backTab = tabs[index - 1];
            props.dispatch({
                type: "tabsReducer/removeTabs",
                payload: {keys: [targetKey]}
            });
            tabChange(backTab.key)
        }
    }, [tabs]);

    const openMenu = useCallback(() => {
        leftMenuRef.current.resize(getLeftWidth(!isFold ? 80 : 200))
        setIsFold(!isFold);
    }, [isFold]);

    const openUser = useCallback(() => {
        props.dispatch({
            type: "drawerReducer/createDrawer",
            payload: {
                data: {
                    key: "user",
                    component: RightMenu,
                    modalProps: {
                        placement: "right",
                        isDestroy: false,
                        closable: false,
                    },
                    comProps: {}
                }
            }
        })
    }, []);

    const handleTabClick = useCallback((key: string, node: any, index: number) => {
        switch (key) {
            case "refreshPage":
                node.tabParams.key = Math.random();
                node.tabParams.viewKey = Math.random();
                tabsRef.current.splice(index, 1, node);
                //清空col缓存
                setViewMap(node.tabParams.viewName, null, 'table')
                setTabs([...tabsRef.current]);
                break;
            case "closeCur":
                const backTab = tabs[index - 1];
                isTabChangingRef.current = true;
                props.dispatch({
                    type: "tabsReducer/removeTabs",
                    payload: {keys: [node.key]}
                });
                tabChange(backTab.key);
                break;
            case "closeOther":
                props.dispatch({
                    type: "tabsReducer/removeTabs",
                    payload: {keys: tabs.filter((i: any) => (i.key !== node.key)).map((k: any) => (k.key))}
                });
                break;
            case "closeLeft":
                props.dispatch({
                    type: "tabsReducer/removeTabs",
                    payload: {keys: tabs.filter((_n: any, i: any) => (i < index)).map((k: any) => (k.key))}
                });
                break;
            case "closeRight":
                props.dispatch({
                    type: "tabsReducer/removeTabs",
                    payload: {keys: tabs.filter((_n: any, i: any) => (i > index)).map((k: any) => (k.key))}
                });
                break;
            case "closeAll":
                isTabChangingRef.current = true;
                props.dispatch({
                    type: "tabsReducer/removeAllTabs",
                    payload: {}
                });
                tabChange("home")
                break;
        }
    }, [tabs]);

    const getTabLabel = useCallback((node: any, index: number) => {
        let newTabsMenu = [...tabMenu]
        if (tabs.length < 3) {
            newTabsMenu.splice(2, 3);
        } else if (index === 1) {
            newTabsMenu.splice(3, 1);
        } else if (index === tabs.length - 1) {
            newTabsMenu.splice(4, 1);
        }
        return (
            <Dropdown
                overlayClassName="sf_core_main_layout_content_tabs_main_title"
                placement={"bottom"}
                trigger={["contextMenu"]}
                menu={{
                    items: newTabsMenu,
                    onClick: ({key}) => {
                        handleTabClick(key, node, index)
                    }
                }}>
                <div>
                    {getLocale(node.labelCn, node.labelEn, node.labelPt) || node.label}
                </div>
            </Dropdown>
        )
    }, [tabs]);

    const renderHeader = useMemo(() => {
        if (!activeTab) {
            return null
        }
        const userName = userInfo.username.slice(0, 1);
        return (
            <Layout.Header className={"sf_core_main_layout_header"}>
                <Row className="sf_core_main_layout_header_top">
                    <Col span={13} className={"sf_core_main_layout_header_top_menu"}>
                        <div className="sf_core_main_layout_header_top_menu_logo">
                            <img src={logoImg} alt="" onClick={openMenu}/>
                            <div className="sf_core_main_layout_header_top_menu_title">
                                <span>{t("title")}</span>
                            </div>
                        </div>
                        <div className={"sf_core_main_layout_header_top_menu_breadcrumb"}>
                            <Breadcrumb
                                items={activeTab.breadcrumb ? activeTab.breadcrumb.map((item: any) => ({title: getLocale(item.labelCn, item.labelEn, item.labelPt)})) : []}/>
                        </div>
                    </Col>
                    <Col span={7} className={"sf_core_main_layout_header_top_search"}>

                    </Col>
                    <Col span={4} className={"sf_core_main_layout_header_top_user"}>
                        <div className={"sf_core_main_layout_header_top_user_info"}>
                            <div className="sf_core_main_layout_header_top_user_info_avatar">
                                <Avatar
                                    onClick={openUser}
                                    icon={userName}
                                />
                            </div>
                        </div>
                    </Col>
                </Row>
            </Layout.Header>
        )
    }, [activeTab, isFold]);

    const renderContent = useMemo(() => {
        if (!activeTab) {
            return null
        }
        return (
            <Layout.Content className={"sf_core_main_layout_content"}>
                <PanelGroup direction="horizontal" style={{height: "100%"}}>
                    <Panel ref={leftMenuRef} defaultSize={getLeftWidth(200)} minSize={getLeftWidth(80)}>
                        <LeftMenu selectMenuId={activeTab.key} isFold={isFold}/>
                    </Panel>
                    <PanelResizeHandle/>
                    <Panel className="sf_core_main_layout_content_tabs">
                        <Tabs
                            type={"editable-card"}
                            hideAdd
                            animated={true}
                            className={"sf_core_main_layout_content_tabs_main"}
                            items={tabs.map((item: any, index: number) => {
                                const {key, tabParams, tabType = "tab"}:
                                    {
                                        key: string,
                                        tabParams: any,
                                        tabType: string
                                    } = item;
                                let Com = getComByType(tabType);
                                return {
                                    ...item,
                                    key: key,
                                    label: getTabLabel(item, index),
                                    children: <Com key={key} {...tabParams}/>
                                };
                            })}
                            onChange={(activeKey: string) => {
                                tabChange(activeKey)
                            }}
                            onEdit={tabEdit}
                            activeKey={activeTab.key}
                            size={"small"}
                        />
                    </Panel>
                </PanelGroup>
            </Layout.Content>
        )
    }, [tabs, activeTab, isFold]);

    const renderMain = useMemo(() => {
        if (!activeTab) {
            return null
        }
        return (
            <div className="sf_core_main">
                <Layout className={"sf_core_main_layout"}>
                    {renderHeader}
                    {renderContent}
                </Layout>
            </div>
        )
    }, [isFold, tabs, activeTab]);

    return (renderMain);
};

export default coreConnect("tabsReducer", "themeReducer")(React.memo(Main));